#include <iostream>
#include <sys/timeb.h>
#include <time.h>

#include "CServiceProxy.h"

#include "space/CMessage.h"
#include "space/CKeyValue.h"

//#ifndef INFINITE
//#define INFINITE
//#endif

using namespace std;

int getRandom()
{
	struct timeb itb;
	struct tm *lt;
	ftime(&itb);
	lt = localtime(&itb.time);
	srand(lt->tm_sec+itb.millitm);

	int random_port = rand();

	return random_port;
}

int main(int argc, char **argv)
{
	if(argc<2) {
		cout << "==============================================" << endl;
		cout << "For CGI Server : " << argv[0] << endl;
		cout << "For Stand-alone Server : " << argv[0] << " <port>" << endl;
		cout << "==============================================" << endl;
	}

#ifdef INFINITE
	for(long num=0;;num++) {
	cout << "============= " << num << " ============" << endl;
#endif

	CServiceProxy proxy;
	if(argc>1) proxy.connect("localhost", atoi(argv[1]));

	cout << "=========================================================" << endl;
	cout << "[test]Echo" << endl;
	cout << "=========================================================" << endl;
	CObjectArray *pobjs = new CObjectArray(3);
	//pobjs->grow(1);
	(*pobjs)[0] = new cube__CMessage();
	(*pobjs)[1] = new cube__CMessage();
	(*pobjs)[2] = new cube__CMessage();
	dynamic_cast<cube__CMessage *>((*pobjs)[0])->set("[echo1]woorung nara");
	dynamic_cast<cube__CMessage *>((*pobjs)[1])->set("[echo2]this is test");
	dynamic_cast<cube__CMessage *>((*pobjs)[2])->set("[echo3]oops from here");

	cube__CService echo_service;
	echo_service.service("sample.echo.service2");

	struct cube__invokeResponse res1;

	// invoke echo service
	if(proxy.invoke(&echo_service, pobjs, res1)!=SOAP_OK) {
		soap_print_fault(proxy.soap(), stderr);

		delete (*pobjs)[0];
		delete (*pobjs)[1];
		delete (*pobjs)[2];
		delete pobjs;

		return -1;
	}

	cout << "-------------- sample.echo.service2 -------------" << endl;
	cout << "response size = " << ((CObjectArray *)res1.out)->__size << endl;

	for(int i=0;i<((CObjectArray *)res1.out)->__size;i++) {
		cout << "[" << i << "]";
		dynamic_cast<cube__CMessage *>(((CObjectArray *)res1.out)->__ptr[i])->print();
	}

	delete (*pobjs)[0];
	delete (*pobjs)[1];
	delete (*pobjs)[2];
	delete pobjs;





	cout << endl << endl;
	cout << "=========================================================" << endl;
	cout << "[test]Discovery" << endl;
	cout << "=========================================================" << endl;
	pobjs = new CObjectArray();
	pobjs->grow(1);
	(*pobjs)[0] = new cube__CMessage();
	dynamic_cast<cube__CMessage *>((*pobjs)[0])->set("all");
	//dynamic_cast<cube__CMessage *>((*pobjs)[0])->set("sample.discovery.service2");

	cube__CService discovery_service;
	discovery_service.service("sample.discovery.service1");

	struct cube__invokeResponse res2;

	// invoke discovery service
	if(proxy.invoke(&discovery_service, pobjs, res2)!=SOAP_OK) {
		soap_print_fault(proxy.soap(), stderr);

		delete (*pobjs)[0];
		delete pobjs;

		return -1;
	}

	cout << "-------------- sample.discovery.service1 -------------" << endl;
	cout << "response size = " << ((CObjectArray *)res2.out)->__size << endl;

	for(int i=0;i<((CObjectArray *)res2.out)->__size;i++) {
		cout << "[" << i << "]";
		dynamic_cast<cube__CMessage *>(((CObjectArray *)res2.out)->__ptr[i])->print();
	}

	delete (*pobjs)[0];
	delete pobjs;



	cout << endl << endl;
	cout << "=========================================================" << endl;
	cout << "[test]Space" << endl;
	cout << "=========================================================" << endl;

	char rand_num[256];
	sprintf(rand_num,"%d",getRandom());

	// write
	pobjs = new CObjectArray(6);
	(*pobjs)[0] = new cube__CKeyValue();
	(*pobjs)[1] = new cube__CKeyValue();
	(*pobjs)[2] = new cube__CKeyValue();
	(*pobjs)[3] = new cube__CKeyValue();
	(*pobjs)[4] = new cube__CKeyValue();
	(*pobjs)[5] = new cube__CKeyValue();
	dynamic_cast<cube__CKeyValue *>((*pobjs)[0])->set("command", "write");
	dynamic_cast<cube__CKeyValue *>((*pobjs)[1])->set(rand_num, "[message1]this is the 1st message");
	dynamic_cast<cube__CKeyValue *>((*pobjs)[2])->set(rand_num, "[message2]this is the 2nd message");
	dynamic_cast<cube__CKeyValue *>((*pobjs)[3])->set(rand_num, "[message3]this is the 3rd message");
	dynamic_cast<cube__CKeyValue *>((*pobjs)[4])->set(rand_num, "[message4]this is the 4th message");
	dynamic_cast<cube__CKeyValue *>((*pobjs)[5])->set(rand_num, "[message5]this is the 5th message");

	cout << "[write] 5 messages" << endl;

	cube__CService space_service;
	space_service.service("sample.space.service");

	struct cube__invokeResponse res3;

	// invoke space service : write
	if(proxy.invoke(&space_service, pobjs, res3)!=SOAP_OK) {
		soap_print_fault(proxy.soap(), stderr);

		delete (*pobjs)[0];
		delete (*pobjs)[1];
		delete (*pobjs)[2];
		delete (*pobjs)[3];
		delete (*pobjs)[4];
		delete (*pobjs)[5];
		delete pobjs;

		return -1;
	}

	cout << "-------------- sample.space.service -------------" << endl;
	cout << "response size = " << ((CObjectArray *)res3.out)->__size << endl;

	for(int i=0;i<((CObjectArray *)res3.out)->__size;i++) {
		cout << "[" << i << "]"; 
		dynamic_cast<cube__CKeyValue *>(((CObjectArray *)res3.out)->__ptr[i])->print();
	}

	delete (*pobjs)[0];
	delete (*pobjs)[1];
	delete (*pobjs)[2];
	delete (*pobjs)[3];
	delete (*pobjs)[4];
	delete (*pobjs)[5];
	delete pobjs;


	// take
	pobjs = new CObjectArray(1);
	(*pobjs)[0] = new cube__CKeyValue();
	dynamic_cast<cube__CKeyValue *>((*pobjs)[0])->set("command", "take");

	cout << "[take] all messages" << endl;

	struct cube__invokeResponse res4;

	// invoke space service
	if(proxy.invoke(&space_service, pobjs, res4)!=SOAP_OK) {
		soap_print_fault(proxy.soap(), stderr);

		delete (*pobjs)[0];
		delete pobjs;

		return -1;
	}

	cout << "-------------- sample.space.service -------------" << endl;
	cout << "response size = " << ((CObjectArray *)res4.out)->__size << endl;

	for(int i=0;i<((CObjectArray *)res4.out)->__size;i++) {
		cout << "[" << i << "]";
		dynamic_cast<cube__CKeyValue *>(((CObjectArray *)res4.out)->__ptr[i])->print();
	}

	delete (*pobjs)[0];
	delete pobjs;


	// read
	pobjs = new CObjectArray(1);
	(*pobjs)[0] = new cube__CKeyValue();
	dynamic_cast<cube__CKeyValue *>((*pobjs)[0])->set("command", "read");

	cout << "[read] a message" << endl;

	struct cube__invokeResponse res5;

	// invoke space service
	if(proxy.invoke(&space_service, pobjs, res5)!=SOAP_OK) {
		soap_print_fault(proxy.soap(), stderr);

		delete (*pobjs)[0];
		delete pobjs;

		return -1;
	}

	cout << "-------------- sample.space.service -------------" << endl;
	cout << "response size = " << ((CObjectArray *)res5.out)->__size << endl;

	for(int i=0;i<((CObjectArray *)res5.out)->__size;i++) {
		cout << "[" << i << "]";
		dynamic_cast<cube__CKeyValue *>(((CObjectArray *)res5.out)->__ptr[i])->print();
	}

	delete (*pobjs)[0];
	delete pobjs;

	

	cout << endl << endl;
	cout << "=========================================================" << endl;
	cout << "[test]Key-Value Sort" << endl;
	cout << "=========================================================" << endl;


	map<string,string> in;
	map<string,string> out;

	in["woorung nara"] = "this is woorung nara value";
	in["1. key"]= "this is key 1 value";
	in["2. key"] = "this is key 2 value";
	in["hahah"] = "what the heck";
	in["hmmmm"] = "huck is this?";
	in["okay"] = "that's good";
	in["wow"] = "what is this?";
	in["key is the important"] = "value is extra data";
	in["the key"] = "the value";
	in["3-day"] = "3-night";

	if(proxy.invoke("keyvalue.sort.service", in, out)<0) exit(-1);

	cout << "[after sort]" << endl;
	cout << "----------------------------------------------------" << endl;
	map<string,string>::iterator item = out.begin();
	while(item!=out.end()) {
		cout << item->first << "\t" << item->second << endl;

		item++;
	}






/*
	cout << endl << endl;
	cout << "=========================================================" << endl;
	cout << "[test]Event Notification Test" << endl;
	cout << "=========================================================" << endl;

	pobjs = new CObjectArray(3);
	(*pobjs)[0] = new cube__CKeyValue();
	(*pobjs)[1] = new cube__CKeyValue();
	(*pobjs)[2] = new cube__CKeyValue();
	dynamic_cast<cube__CKeyValue *>((*pobjs)[0])->set("woorung nara", "this is woorung nara value");
	dynamic_cast<cube__CKeyValue *>((*pobjs)[1])->set("1. key", "this is key 1 value");
	dynamic_cast<cube__CKeyValue *>((*pobjs)[2])->set("2. key", "this is key 2 value");


	cout << "[event] containing 3 key-values" << endl;

	struct cube__event e;
	e.type = EVENT_SUBSCRIBE;
	e.data = pobjs;

	// invoke space service : write
	if(proxy.trigger("event.notification.service", &e)!=SOAP_OK) {
		soap_print_fault(proxy.soap(), stderr);

		delete (*pobjs)[0];
		delete (*pobjs)[1];
		delete (*pobjs)[2];
		delete pobjs;

		return -1;
	}

	delete (*pobjs)[0];
	delete (*pobjs)[1];
	delete (*pobjs)[2];
	delete pobjs;
*/


#ifdef INFINITE
}
#endif

        return 0;
}
